#include "vc1dec_definitions.h"
#include "vc1stream.h"
#include "vc1dec_api.h"
#include "vc1vlc.h"
#include "vc1tables.h"
#include "vc1bitplane.h"

static U32_VC1 DecodePQuant(sVC1Decoder* pDec)
{
	sVC1Stream* pStream = &pDec->stream;
	U8_VC1 pquant  = 0;

	U8_VC1 pqdiff = VC1GetBits(pStream,3);
	if(pqdiff == 7)
	{
		U8_VC1 abspq = VC1GetBits(pStream,5);
		pquant = abspq;
	}
	else
		pquant = pDec->pquant + pqdiff + 1;

	return pquant;
}

static HRESULT_VC1 DecodeVOPDQuant(sVC1Decoder* pDec)
{
	HRESULT_VC1 rt = VC1_OK;
	sVC1Stream* pStream = &pDec->stream;
	U8_VC1 value = 0;

	pDec->boundryedge = 0;
	pDec->dquantfrm = 0;

	if(pDec->dquant == 2)
	{
		pDec->dquantfrm = 1;///quantizer can vary in frames
		pDec->boundryedge = 0x0f;//all edges
		pDec->pquant = DecodePQuant(pDec);
		return VC1_OK;
	}

	value = VC1GetBits(pStream,1);
	if(value == 1)
	{
		U8_VC1 dqprofile = 0;
		pDec->dquantfrm = 1;///quantizer can vary in frames
		value = VC1GetBits(pStream,2);
		dqprofile = value;
		if(dqprofile == 0)
			pDec->boundryedge = 0x0f;
		else if(dqprofile == 1)
		{
			U8_VC1 dqdbedge = VC1GetBits(pStream,2);
			if(dqdbedge != 3)
				pDec->boundryedge = (3 << dqdbedge);
			else
				pDec->boundryedge = 9;//bottom left
		}
		else if(dqprofile == 2)
		{
			U8_VC1 dqsbedge = VC1GetBits(pStream,2);
			pDec->boundryedge = (1 << dqsbedge);
		}
		else
			pDec->dqbilevel = VC1GetBits(pStream,1);

		if(pDec->dqbilevel || pDec->boundryedge)
		{
			pDec->pquant = DecodePQuant(pDec);
		}
	}
	return rt;
}

static HRESULT_VC1 VC1DecMVMode(sVC1Decoder* pDec)
{
	HRESULT_VC1 rt = VC1_OK;
	I8_VC1 value;
	sVC1Stream* pStream = &pDec->stream;
	if(pDec->ePictureType == VC1_PICTURE_P)
	{
		I8_VC1 index = 0;
		value = VC1GetBits(pStream,1);
		if(value == 1)//0x1
			index = 0;
		else
		{
			value = VC1GetBits(pStream,1);
			if(value == 1)//0x01
				index = 1;
			else
			{
				value = VC1GetBits(pStream,1);
				if(value == 1)///0x001
					index = 2;
				else
				{
					value = VC1GetBits(pStream,1);
					if(value == 1)////0x0001
						index = 4;
					else
						index = 3;
				}
			}
		}

		if(pDec->pquant <= 12)//High rate
			pDec->mvmode = VC1PHIGHRATEMVMODE[index];
		else
			pDec->mvmode = VC1PLOWRATEMVMODE[index];

		if(pDec->mvmode == VC1_MVModeIntensityCompensation)
		{
			value = VC1GetBits(pStream,1);
			if(value == 1)//0x1
				index = 0;
			else
			{
				value = VC1GetBits(pStream,1);
				if(value == 1)//0x01
					index = 1;
				else
				{
					value = VC1GetBits(pStream,1);
					if(value == 1)///0x001
						index = 2;
					else
						index = 3;
				}
			}

			if(pDec->pquant <= 12)//High rate
				pDec->mvmode2 = VC1PHIGHRATEMVMODE[index];
			else
				pDec->mvmode2 = VC1PLOWRATEMVMODE[index];

			pDec->lumscale = VC1GetBits(pStream,6);
			pDec->lumshift = VC1GetBits(pStream,6);
		}
		else
			pDec->mvmode2 = VC1_MVMode1MV;
	}
	else///b picture
	{
		value = VC1GetBits(pStream,1);
		if(value == 1)
			pDec->mvmode = VC1_MVMode1MV;
		else
			pDec->mvmode = VC1_MVMode1MVHalfPelBilinear;
	}

	return rt;
}

HRESULT_VC1 VC1DecPicHeader_sm(sVC1Decoder* pDec)
{
	HRESULT_VC1 rt = VC1_OK;
	I8_VC1 value = 0;
	I8_VC1 index = 0;
	sVC1Stream* pStream = &pDec->stream;

	if(pDec->finterpflag)
	{
		value = VC1GetBits(pStream,1);
	}

	value = VC1GetBits(pStream,2);

	if(pDec->rangered)
	{
		value = VC1GetBits(pStream,1);
		pDec->rangedfrm = value;
	}

	value = VC1GetBits(pStream,1);
	if(pDec->maxbframes = 0)///
	{
		if(value == 0)///I frame
			pDec->ePictureType = VC1_PICTURE_I;
		else
			pDec->ePictureType = VC1_PICTURE_P;
	}
	else
	{
		if(value == 1)///p frame
			pDec->ePictureType = VC1_PICTURE_P;
		else
		{
			value = VC1GetBits(pStream,1);
			if(value == 1)
				pDec->ePictureType = VC1_PICTURE_I;
			else
				pDec->ePictureType = VC1_PICTURE_B;
		}
	}

	if(pDec->ePictureType == VC1_PICTURE_B)
	{
		value = VC1GetBits(pStream,3);///
		pDec->bfraction = value;
		if(0x7 == value)
		{
			value = VC1GetBits(pStream,4);///
			pDec->bfraction += value;
			if(value == 0xF)/////BI frame
				pDec->ePictureType = VC1_PICTURE_BI;
		}
	}

	if(pDec->ePictureType == VC1_PICTURE_I)
	{
		value = VC1GetBits(pStream,7);
		pDec->bf = value;
	}

	value = VC1GetBits(pStream,5);
	index = value;

	if(index <= 8)
	{
		value = VC1GetBits(pStream,1);
		pDec->halfqp = value;
	}

	if(pDec->quantizer == 0x1)
	{
		value = VC1GetBits(pStream,1);
		//pDec->pquantizer = value;
		if(value == 0)
			pDec->nonuniform = 1;
		else
			pDec->nonuniform = 0;

		pDec->pquant = index;
	}
	else
	{
		if(pDec->quantizer == 0x0)////implicit
		{
			if(index > 8)
			{
				pDec->nonuniform = 1;
				pDec->pquant = VC1ImplicitQuantizer[index];
			}
			else
				pDec->nonuniform = 0;
		}
		else if(pDec->quantizer == 0x10)
		{
			pDec->nonuniform = 1;
			pDec->pquant = index;
		}
		else
		{
			pDec->nonuniform = 0;
			pDec->pquant = index;
		}
	}

	if(pDec->ext_mv)
	{
		value = VC1ShowBits(pStream,3);
		if(value <= 0x3)/////
		{
			pDec->mvrange = VC1_MVRange64_32;
			VC1DumpBits(pStream,1);
		}
		else if(value <= 0x5)
		{
			pDec->mvrange = VC1_MVRange128_64;
			VC1DumpBits(pStream,2);
		}
		else if(value == 0x6)
		{
			pDec->mvrange = VC1_MVRange512_128;
			VC1DumpBits(pStream,3);
		}
		else
		{
			pDec->mvrange = VC1_MVRange1024_256;
			VC1DumpBits(pStream,3);
		}
	}

	if(pDec->ePictureType == VC1_PICTURE_I || pDec->ePictureType == VC1_PICTURE_P)
	{
		if(pDec->multires)
		{
			value = VC1ShowBits(pStream,2);
			pDec->respic = value;
		}
	}

	if(pDec->ePictureType == VC1_PICTURE_B || pDec->ePictureType == VC1_PICTURE_P)
		if((rt = VC1DecMVMode(pDec)) != VC1_OK)
			return rt;

	if(pDec->ePictureType == VC1_PICTURE_P)
	{
		if(pDec->mvmode == VC1_MVModeMixedMV || pDec->mvmode2 == VC1_MVModeMixedMV)///bitplane decoding---mvtypemb
			if((rt = VC1DecodeBitplane(pDec,0)) != VC1_OK)
				return rt;
	}

	if(pDec->ePictureType == VC1_PICTURE_B)
	{
		if((rt = VC1DecodeBitplane(pDec,0)) != VC1_OK)//directmb
			return rt;
	}

	if((rt = VC1DecodeBitplane(pDec,1)) != VC1_OK)//skipmb
			return rt;

	
	value = VC1GetBits(pStream,2);
	pDec->mvtab = value;

	value = VC1GetBits(pStream,2);
	pDec->cbptab = value;

	if(pDec->dquant != 0)
		DecodeVOPDQuant(pDec);

	if(pDec->vstransform)
	{
		U8_VC1 value = VC1GetBits(pStream,1);
		pDec->ttmbf = value;
		if(value == 1)
			pDec->ttfrm = VC1GetBits(pStream,2);

	}

	value = VC1GetBits(pStream,1);
	if(value == 0)
		pDec->transacfrm = 0;
	else
	{
		value = VC1GetBits(pStream,1);
		if(value == 0)
			pDec->transacfrm = 1;
		else
			pDec->transacfrm = 2;
	}

	if(pDec->ePictureType == VC1_PICTURE_I || pDec->ePictureType == VC1_PICTURE_P)
	{
		value = VC1GetBits(pStream,1);
		if(value == 0)
			pDec->transacfrm2 = 0;
		else
		{
			value = VC1GetBits(pStream,1);
			if(value == 0)
				pDec->transacfrm2 = 1;
			else
				pDec->transacfrm2 = 2;
		}
	}

	value = VC1GetBits(pStream,1);
	pDec->transdctab = value;

	pDec->first_mode3 = 1;
	return rt;
}